package jfds.clases.tokens;

import java.util.Arrays;
import java.util.List;


public class Tokenizer {
	private String entrada;
	private String Salida = "OK";
	private int accion;
	public Tokenizer (String input, int acc) {
		this.entrada = input;
		this.accion = acc;
		AccionARealizar();
	}
	
	int index, largo=0;
	 List<Character> letras = Arrays.asList( 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 
			   'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
			   'U', 'V', 'W', 'X', 'Y', 'Z', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '*', '-', '_', ',', '"', '.', ' ');
	 // evaluo la aacion a realizar para lo que le doy el valor al que va a recorrer la variable index antes de que el token de un error de reconociomiento
	 private int AccionARealizar(){
		 switch (accion){
		    case 1 : return largo=12;
		    case 99: return largo= entrada.length();
		  	default: return largo=0;
		 }
	 }
	 // devuelve el siguiente token en la entrada
	Token nextToken(){
		while (index < largo) {
			char c = 0;
			try {
				c = entrada.charAt(index);
				switch (c){
			    case 'A' : consumir(); return new Token(Token._A);
			    case 'C' : consumir(); return new Token(Token._C);
			    case 'D' : consumir(); return new Token(Token._D);
			    case 'E' : consumir(); return new Token(Token._E);
				case 'F' : consumir(); return new Token(Token._F);
				case 'I' : consumir(); return new Token(Token._I);
				case 'K' : consumir(); return new Token(Token._K);
				case 'L' : consumir(); return new Token(Token._L);
				case 'N' : consumir(); return new Token(Token._N);
				case 'P' : consumir(); return new Token(Token._P);
				case 'R' : consumir(); return new Token(Token._R);
				case 'S' : consumir(); return new Token(Token._S);
				case 'U' : consumir(); return new Token(Token._U);
				case 'V' : consumir(); return new Token(Token._V);
				case 'X' : consumir(); return new Token(Token._X);
				case 'W' : consumir(); return new Token(Token._W);
				case '0' : consumir(); return new Token(Token._00);
				case '1' : consumir(); return new Token(Token._01);
				case '2' : consumir(); return new Token(Token._02);
				case '3' : consumir(); return new Token(Token._03);
				case '4' : consumir(); return new Token(Token._04);
				case '5' : consumir(); return new Token(Token._05);
				case '6' : consumir(); return new Token(Token._06);
				case '7' : consumir(); return new Token(Token._07);
				case '8' : consumir(); return new Token(Token._08);
				case '9' : consumir(); return new Token(Token._09);
				case '(' : consumir(); return new Token(Token._parenA);
				case ')' : consumir(); return new Token(Token._parenC);
				case '*' : consumir(); return new Token(Token._asterizco);
				case '.' : consumir(); return new Token(Token._punto);
				case '-' : consumir(); return new Token(Token._guion);
				case ' ' : consumir(); return new Token(Token._spaces);
				default: if (letras.contains(c)){
					return identificador();
				}else {
					Salida += "Caracter no reconocido: " + c;
					Salida +=  "\n"; 
				}
			}
			} catch (Exception e) {
				Salida = "NOOK";
				return new Token(Token.EOF);
			}
		}
		return new Token(Token.EOF);
	}
	
	Token nextToken2(){
		while (index < largo) {
			char c = entrada.charAt(index);
			switch (c){
			    case 'A' : return new Token(Token._A);
			    case 'C' : return new Token(Token._C);
			    case 'D' : return new Token(Token._D);
			    case 'E' : return new Token(Token._E);
				case 'F' : return new Token(Token._F);
				case 'I' : return new Token(Token._I);
				case 'K' : return new Token(Token._K);
				case 'L' : return new Token(Token._L);
				case 'N' : return new Token(Token._N);
				case 'P' : return new Token(Token._P);
				case 'R' : return new Token(Token._R);
				case 'S' : return new Token(Token._S);
				case 'U' : return new Token(Token._U);
				case 'V' : return new Token(Token._V);
				case 'X' : return new Token(Token._X);
				case 'W' : return new Token(Token._W);
				case '0' : return new Token(Token._00);
				case '1' : return new Token(Token._01);
				case '2' : return new Token(Token._02);
				case '3' : return new Token(Token._03);
				case '4' : return new Token(Token._04);
				case '5' : return new Token(Token._05);
				case '6' : return new Token(Token._06);
				case '7' : return new Token(Token._07);
				case '8' : return new Token(Token._08);
				case '9' : return new Token(Token._09);
				case '(' : return new Token(Token._parenA);
				case ')' : return new Token(Token._parenC);
				case '*' : return new Token(Token._asterizco);
				case '.' : return new Token(Token._punto);
				case '-' : return new Token(Token._guion);
				case ' ' : return new Token(Token._spaces);
				default: if (letras.contains(c)){
					return identificador();
				}else {
					Salida += "Caracter no reconocido: " + c;
					Salida +=  "\n"; 
				}
				
			}
		}
		return new Token(Token.EOF);
	}
	Token bucle(){
		while (index < largo) {
			char c = entrada.charAt(index);
			switch (c){
				case '.' : return new Token(Token._punto);
				case '-' : return new Token(Token._guion);
//				case ' ' : consumir(); return new Token(Token._spaces);
				case '8' : consumir(); return new Token(Token._08);
				default: if (letras.contains(c)){
					return PuntoYAparte();
				}
				
			}
		}
		return new Token(Token.EOF);
	}
	
	 // avanza el indice 
    void consumir() { 
        index++;
    }
    // Devuelve un token de tipo identificador
    private Token identificador() {
    	 StringBuilder sb = new StringBuilder();
         char c;
         while (index < largo && letras.contains(c = entrada.charAt(index))){
        	 consumir();
        	 sb.append(c);
         }
         return new Token(Token.IDENTIFICADOR, sb.toString() );
    }
    
    // Devuelve un token de tipo punto
    private Token PuntoYAparte() {
    	 StringBuilder sb = new StringBuilder();
         char c = 0;
         while ((index < largo && letras.contains(c = entrada.charAt(index))) && (c != ' ' && c != '.')){
        	 consumir();
        	 sb.append(c);
         }
         return new Token(Token._punto, sb.toString() );
    }
    
 // Devuelve un token de tipo punto
    private Token EspaciosYAparte() {
    	 StringBuilder sb = new StringBuilder();
         char c = 0;
         while ((index < largo && letras.contains(c = entrada.charAt(index))) && (c != ' ' && c != '.')){
        	 consumir();
        	 sb.append(c);
         }
         return new Token(Token._punto, sb.toString() );
    }

	public String getSalida() {
		return Salida;
	}

	public void setSalida(String salida) {
		Salida = salida;
	}    
    
}
